package com.trans.handler;

import com.trans.anno.DataBase;
import com.trans.anno.Translator;
import com.trans.auxiliary.HandleFullRecord;
import com.trans.auxiliary.HandleRecord;
import com.trans.auxiliary.Params;
import com.trans.utils.SpringUtils;
import lombok.AllArgsConstructor;
import lombok.EqualsAndHashCode;
import lombok.extern.slf4j.Slf4j;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;

import java.text.MessageFormat;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Description mybatisPlus转换对象，目前支持唯一键字段
 * @Author xwduo
 * @Date 2022年03月01日 08:51
 **/
@Slf4j
@SuppressWarnings("all")
public class DbUnique implements TranslateHandle<DbUnique.DataUniqueKey,Map<String,Object>> {

    private static final String SPLITER = "::";
    private static final String COLUM = "`%s`";
    private static final String COMMA = ",";

    @Override
    public Object doHandle(HandleRecord record, Map<DataUniqueKey, Map<String,Object>> cacheMap) {
        DataBase dataBase = record.getAnnotation(DataBase.class);
        Object curItemVal = record.getVal();
        Map<String,Object> showMap = new HashMap<>();
        if (null != dataBase && dataBase.showColum() !=null && dataBase.showColum().length>0 && null != curItemVal) {
            String table = dataBase.table();
            String colum = dataBase.colum();
            String columVal = String.valueOf(curItemVal);
            DataUniqueKey dataUniqueKey = convert2Key(table, colum, columVal);
            Map<String, Object> objectMap = cacheMap.get(dataUniqueKey);
            for (String showColum : dataBase.showColum()) {
                showMap.put(showColum,objectMap.get(showColum));
            }
        }
        return showMap;
    }

    @Override
    public  Map<DbUnique.DataUniqueKey, Map<String,Object>> cache(List<HandleFullRecord> recordList) {
        //表名::key-结果集
        Map<TableUniqueKey, Set<String>> searchMap = new HashMap<>();
        Map<TableUniqueKey, Set<String>> keyMaps = new HashMap<>();
        for (HandleFullRecord handleFullRecord : recordList) {
            Translator translator = handleFullRecord.translator;
            Params params = handleFullRecord.params;
            if (null != translator && null != params) {
                DataBase dataBase = params.getAnnotation(DataBase.class);
                if (null != dataBase && dataBase.showColum() !=null &&dataBase.showColum().length>0 ) {
                    String table = dataBase.table();
                    String colum = dataBase.colum();
                    TableUniqueKey tableUniqueKey = convert2Key(table, colum);
                    if(searchMap.containsKey(tableUniqueKey)){
                        searchMap.get(tableUniqueKey).addAll(Arrays.asList(dataBase.showColum()));
                    }else {
                        searchMap.put(tableUniqueKey,new HashSet<>(Arrays.asList(dataBase.showColum())));
                    }
                    if(null != handleFullRecord.getVal()){
                        String keyValue = String.valueOf(handleFullRecord.getVal());
                        if(keyMaps.containsKey(tableUniqueKey)){
                            keyMaps.get(tableUniqueKey).add(keyValue);
                        }else {
                            keyMaps.put(tableUniqueKey,new HashSet<>(Arrays.asList(keyValue)));
                        }
                    }
                }
            }
        }
        NamedParameterJdbcTemplate jdbcTemplate = SpringUtils.getBean(NamedParameterJdbcTemplate.class);
        Map<DataUniqueKey, Map<String,Object>> dataMap = new HashMap<>();
        for (Map.Entry<TableUniqueKey, Set<String>> entry : searchMap.entrySet()) {
            if(keyMaps.containsKey(entry.getKey())){
                TableUniqueKey key = entry.getKey();
                List<String> show = new ArrayList<>(entry.getValue());
                String table = key.tableName;
                String keyColum = key.keyColum;
                String sqlFormat =  "select {1},{2} from {0} where {1} in (:keys) ";
                String toCol = show.stream().map(DbUnique::convert2SafeSearch).collect(Collectors.joining(COMMA));
                String sql = MessageFormat.format(sqlFormat, table, keyColum, toCol);
                Map<String, Object> paramMap = new HashMap<>();
                paramMap.put("keys", keyMaps.get(entry.getKey()));
                jdbcTemplate.query(sql, paramMap, rs -> {
                    Map<String,Object> dataRs = new HashMap<>();
                    String keyColumVal = rs.getString(1);
                    dataRs.put(keyColum,keyColumVal);
                    for (int i = 0; i < show.size(); i++) {
                        String showColum = show.get(i);
                        Object showColumVal = rs.getObject(i+2);
                        dataRs.put(showColum,showColumVal);
                    }
                    dataMap.put(convert2Key(table,keyColum,keyColumVal), dataRs);
                });
            }
        }
        return dataMap;
    }

    @Override
    public int order() {
        return 0;
    }

    private static TableUniqueKey convert2Key(String table , String keyColum){
        return new TableUniqueKey(table,keyColum);
    }

    private static DataUniqueKey convert2Key(String table , String keyColum,String keyValue){
        return new DataUniqueKey(table,keyColum,keyValue);
    }

    private static String convert2SafeSearch(String key){
        return String.format(COLUM,key);
    }

    @AllArgsConstructor
    @EqualsAndHashCode
    public static class DataUniqueKey{

        private final String tableName;

        private final String keyColum;

        private final String keyColumVal;



    }

    @AllArgsConstructor
    @EqualsAndHashCode
    public static class TableUniqueKey{

        private final String tableName;

        private final String keyColum;

    }
}
